package com.jstyle.blesdkota.ble2318ota_plugin;

import static android.content.ContentValues.TAG;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.NonNull;

import com.goodix.ble.gr.libdfu.EasyDfu;
import com.goodix.ble.gr.toolbox.app.libfastdfu.DfuProgressCallback;
import com.goodix.ble.gr.toolbox.app.libfastdfu.EasyDfu2;
import com.goodix.ble.libcomx.ILogger;

import org.apache.commons.codec.digest.DigestUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;

import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;

/** Ble2318otaPlugin */
public class Ble2318otaPlugin implements FlutterPlugin, MethodCallHandler,ActivityAware, ILogger {
  private MethodChannel channel;

  private Activity activity;
  private String address;
  //固件升级文件
  private String filePath;
  //UI升级文件
  private String colorPath;
  //Dfu是否连接中
  private boolean isConnected = false;

  private String devicesmFilePath;

  private DfuProgressCallback callback = new DfuProgressCallback() {
    @Override
    public void onDfuStart() {
      sendMessage("6");
      Log.e("test","onDfuStart");
    }

    @Override
    public void onDfuProgress(int i) {
      sendMessage("7," + i);
      Log.e("test","onDfuProgress" + i);
    }

    @Override
    public void onDfuComplete() {
      sendMessage("8");
      Log.e("test","onDfuComplete");
    }

    @Override
    public void onDfuError(String s, Error error) {
      sendMessage("9");
      Log.e("test","onDfuError: " + s);
      startDfu();
    }
  };

  private Handler handler = new Handler(){
    @Override
    public void handleMessage(@NonNull Message msg) {
      super.handleMessage(msg);
      switch (msg.what){
        case 0:
          break;
        case 1:
          break;
      }

    }
  };

  // 1 搜素设备 2 停止搜素 3 找到设备 4 准备开始升级
  // 5 创建升级失败 6 开始升级 7 升级进度 8 升级完成 9 升级失败
  private void sendMessage(String text) {
    handler.post(new Runnable() {
      @Override
      public void run() {
        channel.invokeMethod("sendMessage",text);
      }
    });
  }



  @Override
  public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
    channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "ble2318ota_plugin");
    channel.setMethodCallHandler(this);

  }
  BluetoothManager bluetoothManager;
  private void initBlueTools(){
    activity.runOnUiThread(new Runnable() {
      @Override
      public void run() {
        if(mBluetoothAdapter != null){
          bluetoothManager = (BluetoothManager) activity.getSystemService(Context.BLUETOOTH_SERVICE);
          mBluetoothAdapter = bluetoothManager.getAdapter();
        }
      }
    });

  }

  @Override
  public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
//    Log.e("test","onMethodCall: " + call.method);
    if (call.method.equals("getPlatformVersion")) {
      result.success("Android " + android.os.Build.VERSION.RELEASE);
    } else if(call.method.equals("startOta")){
      if(call.hasArgument("path")){
        setFilePath(call.argument("path"));
      }
      if(activity != null){
        scanLeDevice(true);
      }
      result.success("");
    } else if(call.method.equals("initBlueTools")){
      //里面的初始化是不生效的，正在的初始化是在，获取activity里面去初始化，这里只是为了触发Activity的回调
      initBlueTools();
      result.success("");
    } else if(call.method.equals("stopScan")){
      scanLeDevice(false);
      result.success("");
    } else if(call.method.equals("checkFiles")){
      String path = "";
      if(call.hasArgument("binPath")){
        path = call.argument("binPath");
      }
      try {
        File deleteFile = new File(ZipUtils.getFromPath(activity)+"ota/");
        if(deleteFile.exists()){
          deleteFile.delete();
        }
      }catch (Exception e){
        e.printStackTrace();
      }
      ZipUtils.upZipFile(path, ZipUtils.getFromPath(activity)+"ota/");
      File file = new File(ZipUtils.getFromPath(activity)+"ota/");
      if(!file.exists()){
        return;
      }
      File[] files = file.listFiles();
      for (int i = 0; i < files.length; i++) {
//        Log.e("test","fileName: " + files[i].getName());
        if(files[i].getName().contains("app")){
          filePath = files[i].getAbsolutePath();
        }
        if(files[i].getName().toLowerCase().contains("gr")){
          colorPath = files[i].getAbsolutePath();
        }
      }
      File binFile = new File(filePath);
      File binMd5File = new File(colorPath);
      if (!binFile.exists()) {
        Log.i(TAG, "binFile not exists ");
        result.success(new int[]{0,0,0});
      }
      byte[] fileValue = ZipUtils.readFile(binFile);
      byte[] md5Value = ZipUtils.readFile(binMd5File);
      byte[] dd = startFeilipuOTA(fileValue,md5Value);
//      Log.e("test","aaaa---result: " + Arrays.toString(dd));
      int[] data = new int[dd.length];
      for (int i = 0; i < dd.length; i++) {
        data[i] = dd[i];
      }
      result.success(data);
    } else {
      result.notImplemented();
    }
  }

  //解析出47命令
  public static byte[] startFeilipuOTA(byte[] application,byte[] md5) {
    byte[] value = new byte[82];
    value[0] = 0x47;
    if(null!=application){
      System.arraycopy(Md5(application) , 0, value, 2, 16);
      System.arraycopy(md5, 0, value, 18, 64);
    }
    return value;
  }

  private static byte[] Md5(byte[]fileValue){
    return DigestUtils.md5(fileValue);
  }

  private void setFilePath(String path){
    this.devicesmFilePath = path;
  }

  private void startDfu() {
    Log.e("test","startDfu");
    sendMessage("4");
    activity.runOnUiThread(new Runnable() {
      @Override
      public void run() {
        if (targetDevice != null) {
          boolean noFile = true;
          InputStream stream=null;
          try {
            stream = new FileInputStream(filePath);
            if (stream != null) {
              noFile = false;
              // 关键代码
              EasyDfu2 dfu2 = new EasyDfu2();
              dfu2.setLogger(Ble2318otaPlugin.this);
              dfu2.setListener(callback);
              //传入升级参数，设备信息（名字，mac）,升级设备文件流
              dfu2.startDfu(activity, targetDevice, stream);
              stream.close();
            }
            if (noFile) {
              Log.e(TAG,"noFile");
            }
          } catch (IOException e) {
            sendMessage("5");
          }
        }
      }
    });

  }

  private BluetoothAdapter mBluetoothAdapter;
  private boolean mScanning;
  BluetoothDevice targetDevice;
  private void scanLeDevice(final boolean enable) {
    Log.e("test","scanLeDevice: " + enable);
    if (enable) {
      mBluetoothAdapter.startLeScan(mLeScanCallback);
      mScanning = true;
      sendMessage("1");
    } else {
      mBluetoothAdapter.stopLeScan(mLeScanCallback);
      mScanning = false;
      sendMessage("2");
    }
  }
  private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
    @Override
    public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) {
      if(null!=device&&!TextUtils.isEmpty(device.getAddress())){
        activity.runOnUiThread(new Runnable() {
          @Override
          public void run() {
            if(!mScanning)return;
            String deviceName = Utils.decodeDeviceName(scanRecord);
            if (TextUtils.isEmpty(deviceName)){
              deviceName = device.getName();
            }
            String mac = device.getAddress().trim().toUpperCase();
            if (!TextUtils.isEmpty(deviceName)) {
              String NN = deviceName.replace(" ","").trim().toLowerCase();
              if(NN.contains("dfu28")){//这里要判断47 后设备的名字
                sendMessage("3");
                scanLeDevice(false);
                targetDevice = mBluetoothAdapter.getRemoteDevice(mac);
                handler.postDelayed(new Runnable() {
                  @Override
                  public void run() {
                    startDfu();
                  }
                },4000);
              }
            }
          }
        });
      }
    }
  };





  @Override
  public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
    channel.setMethodCallHandler(null);
  }

  @Override
  public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
    activity = binding.getActivity();
    bluetoothManager = (BluetoothManager) binding.getActivity().getSystemService(Context.BLUETOOTH_SERVICE);
    mBluetoothAdapter = bluetoothManager.getAdapter();
  }

  @Override
  public void onDetachedFromActivityForConfigChanges() {

  }

  @Override
  public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {

  }

  @Override
  public void onDetachedFromActivity() {
    activity = null;
  }

  @Override
  public void v(String s, String s1) {

  }

  @Override
  public void d(String s, String s1) {

  }

  @Override
  public void i(String s, String s1) {

  }

  @Override
  public void w(String s, String s1) {

  }

  @Override
  public void e(String s, String s1) {

  }

  @Override
  public void e(String s, String s1, Throwable throwable) {

  }
}
